package ch.ebnoether.xml;

import ch.ebnoether.player.Player;
import ch.ebnoether.player.Score;
import org.xml.sax.SAXException;

import javax.swing.*;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: Frank
 * Date: 20.06.12
 * Time: 20:32
 * To change this template use File | Settings | File Templates.
 */
public class HighscoreXML implements Highscore {

  private File xmlFile;
  private Score score;


  public HighscoreXML() throws IOException, SAXException, ParserConfigurationException {
    this.score = getScore();
    this.xmlFile = createDirAndFile();
    readFile();
  }

  @Override
  public void writeFile() {
    if (xmlFile != null) {
      writeFile(xmlFile);
    }
  }

  private void writeFile(File xmlFile) {
    JAXBContext jaxbContext = null;
    try {
      FileWriter writer = new FileWriter(xmlFile);
      jaxbContext = JAXBContext.newInstance(Score.class);
      Marshaller marshaller = jaxbContext.createMarshaller();
      marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
      marshaller.marshal(getScore(), writer);
    } catch (JAXBException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }


  @Override
  public void readFile() {
    try {
      JAXBContext jaxbContext = JAXBContext.newInstance(Score.class);
      Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
      this.score = (Score) unmarshaller.unmarshal(xmlFile);
    } catch (JAXBException e) {
      e.printStackTrace();
    }
    sortieren(score.getPlayerList());
  }

  @Override
  public void vergleichen(Player player) throws IOException, ParserConfigurationException, SAXException {
    getScore().addNewPlayer(player);
    sortieren(score.getPlayerList());
    highScoreAnzeigen();
    writeFile();
  }

  @Override
  public void highScoreAnzeigen() {
    listeReduzierenMaxZehn();


    JOptionPane.showMessageDialog(
            null,
            getScore().toString(),
            "Hall of Fame",
            JOptionPane.INFORMATION_MESSAGE
    );
  }

  private void listeReduzierenMaxZehn() {
    if (getScore().getPlayerList().size() > 10) {
      ArrayList<Player> temp = new ArrayList<Player>();
      for (int i = 0; i < 10; i++) {
        Player player = getScore().getPlayerList().get(i);
        player.setRang(i + 1);
        temp.add(player);
      }
      getScore().setPlayerList(temp);
    }
  }


  private void sortieren(List<Player> list) {

    // abbruchbestimmung falls keine Sortierung mehr stattgefunden hat
    boolean veraendert = true;

    // aeusere Schleife um Grenze sortierter bereich von oben zu setzen
    for (int i = (list.size() - 1); i >= 1 && veraendert; i--) {
      veraendert = false;

      // unsortierter Bereich von unten her
      for (int j = 1; j <= i; j++) {

        // vergleich der beiden Zahlen
        if (list.get(j - 1).getPunkte() < list.get(j).getPunkte()) {
          Player tmp = list.get(j);
          list.set(j, list.get(j - 1));
          list.set(j - 1, tmp);
          veraendert = true;
        }
      }
    }

    for (int i = 0; i < list.size(); i++) {
      list.get(i).setRang(i + 1);
    }
  }

  private File createDirAndFile() throws IOException {
    String dirPath = System.getenv("LOCALAPPDATA") + "/yatzi/test"; // TODO: test entfernen!!

    File dir = new File(dirPath);
    File xmlFile = new File(dirPath + "/" + "highscore.xml");

    if (!dir.exists()) {
      if (!dir.mkdir()) {
        throw new IOException(dir + " konnte nicht erstellt werden");
      }
    }

    if (!xmlFile.exists()) {
      if (!xmlFile.createNewFile()) {
        throw new IOException(xmlFile + " konnte nicht erstellt werden");
      }
      writeFile(xmlFile);
    }
    return xmlFile;
  }

  public Score getScore() {
    if (score == null) {
      score = new Score();
    }
    return score;
  }
}
